
#ifndef SERVER_H_
#define SERVER_H_

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#include <math.h>
#include <time.h>
#include <string.h>

#define BUF_SIZE	512
#define	MAX_CLIENT	50
#define	MAX_CONNECT	10
#define	HEIGHT		10
#define	WIDTH		10
#define	TIME		10
#define	PORT		4242

#define	ABS(value)	(((value) < 0) ? ((value) * (-1)) : (value))

#define INVENTORY	"{nourriture %d, linemate %d, deraumere %d, sibur %d, mendiane %d, phiras %d, thystame %d}\n"
#define USAGE		"Usage : serveur\n-p numero de port\n-x largeur du Monde\n-y hauteur du Monde\n-n nom_equipe_1 nom_equipe_2 ...\n-c nombre de client autorises au commencement du jeu\n-t delai temporel d'execution des actions"

#define BLACK    "\033[1;30m"
#define RED      "\033[1;31m"
#define GREEN    "\033[1;32m"
#define YELLOW   "\033[1;33m"
#define BLUE     "\033[1;34m"
#define PURPLE   "\033[1;35m"
#define CYAN     "\033[1;36m"
#define WHITE    "\033[1;37m"
#define DEFAUT   "\033[0m"

#define	SERV		0
#define	UNKNOW		1
#define	AI		2
#define	GRAPH		3
#define	DEAD		4
#define	DECO		5

#define SAME_PLACE	0
#define	NORD		1
#define	NORD_OUEST	2
#define	OUEST		3
#define	SUD_OUEST	4
#define	SUD		5
#define	SUD_EST		6
#define	EST		7
#define	NORD_EST	8

#define	NOURRITURE	0
#define	LINEMATE	1
#define	DERAUMERE	2
#define	SIBUR		3
#define	MENDIANE	4
#define	PHIRAS		5
#define	THYSTAME	6
#define	ALL_RC		7

#define	LVL_MAX		8


typedef struct		s_coord
{
  int			x;
  int			y;
}			t_coord;

typedef struct		s_player
{
  int			x;
  int			y;
  char			*team;
  int			level;
  int			life;
  int			look_at;
  int			id;
  int			ressource[ALL_RC];
}			t_player;

typedef struct		s_player_list
{
  t_player		*drone;
  struct s_player_list	*next;
}			t_player_list;

typedef struct		s_egg
{
  int			id;
  int			x;
  int			y;
  char			*team;
  long			time;
  struct s_egg		*next;
}			t_egg;

typedef struct		s_case
{
  int			ressource[ALL_RC];
  t_player_list		*players;
}			t_case;

typedef struct		s_string_list
{
  char			str[BUF_SIZE + 1];
  struct s_string_list	*next;
}			t_string_list;

typedef struct		s_fd
{
  int			fd;
  int			type;
  long			wait;
  int			idaction;
  char			*action_list[10];
  char			*cmd;
  t_string_list		*receive_list;
  t_string_list		*send_list;
  char			buf_read[BUF_SIZE + 1];
  char			buf_write[BUF_SIZE + 1];
  t_player		*pl;
  struct s_fd		*next;
}			t_fd;

typedef struct		s_team
{
  char			*name;
  int			dispo;
  t_player_list		*ia_players;
  t_egg			*eggs;
}			t_team;

typedef struct	s_env
{
  t_fd			*fd;
  t_team		*teams;
  t_case		**map;
  int			max;
  int			new_id;
  int			port;
  int			width;
  int			height;
  int			max_connect;
  int			t;
  long			time_pop;
  struct timeval	elapsed;	
  fd_set		fd_read;
  fd_set		fd_write;
}			t_env;

typedef struct		s_action
{
  char			*cmd;
  int			delay;
  void			(*execute)(t_fd *, t_env *, char *);
  int			id;
}			t_action;

typedef struct		lvlup
{
  int			lvlrequired;
  int			nextlvl;
  int			nb_player;
  int			ressource[ALL_RC];
}			t_lvlup_req;

void			aff_err(char *str);
void			*x_null(void *err, void *res, char *str);
int			x_int(int err, int res, char *str);
void			xstrcat(char **s1, char *s2, int *current_len);
void			parse_option(t_env *e, int ac, char **av, int i);
int			parse_number(char *str);
void			set_default(t_env *e);
void			parse_team_name(t_env *e, int ac, char **av, int *i);
void			parse_check_value(t_env *e);
void			create_player_for_team(t_env *e);
void			create_server(t_env *e);
void			server_accept(t_env *e, int s);
void			parse_check_team(int j, char **av, t_env *e, int deb);
void			parse_action(t_fd *cs, t_env *e, char *tmp);
void			check_action_delay(t_fd *tmp, t_env *e);
int			*generate_ressources(t_env *e);
t_case			**generate_map(int x, int y, int *ressource);
void			aff_map(t_case **map, int x, int y);
void			refresh_fd(t_env *e);
void			check_fd(t_env *e);
void			pop_ressources(t_env *e);
void			loop(t_env *e);
int			calc_mintime(t_env *e);
void			int_to_timeval(struct timeval *timeval, int time);
long			timeval_to_int(struct timeval timeval);
void			calc_elapsed(struct timeval *elapsed);
void			parse_type(char *cmd, t_fd *fd, t_env *env, int i);
void			parse_commande(char *cmd, t_fd *fd, t_env *env);
void			add_to_action_list(t_fd *fd, t_env *e);
void			egg_hatch(t_team *team, t_egg *egg, t_env *e);
void			execute_action(t_env *e);
void			egg_check(t_env *e);
void			check_action_delay(t_fd *tmp, t_env *e);
void			refresh_action_list(char **action_list);
void			add_string_to_list(t_string_list **begin, char *str);
char			*clean_string_list(t_string_list **begin);
void			client_read(t_fd *cs, t_env *e);
void			client_write(t_fd *cs, t_env *e);
t_player		*new_drone(char *team, int x, int y, int t);
void			add_drone_to_team(t_team *team, t_player *drone);
void			add_drone_to_case(t_case **map, int x, int y, t_player *drone);
void			remove_drone_from_team(t_team *team, t_player *drone);
void			remove_drone_from_case(t_case **map, int x, int y, t_player *drone);
void			clean_fd(t_env *e);
void			remove_from_fdlist(t_fd **begin, t_fd *elem);
void			dead(t_fd *fd, t_env *env);
char			**str_to_wordtab(char *str, char del);
void			action_voir_init(t_fd *fd, char **cmd2, int *len, char *cmd);
void			voir_contenu(t_env *e, t_coord deb, char **cmd2, int *len);
void			action_voir_calcul_pos(t_env *e, t_fd *fd, int j, t_coord *deb);
void			action_voir(t_fd *fd, t_env *e, char *cmd);
void			endgame(t_fd *fd, t_env *e);
void			graph_avance(t_fd *fd, t_env *e);
void			action_avance(t_fd *fd, t_env *e, char *cmd);
void			action_droite(t_fd *fd, t_env *e, char *cmd);
void			action_gauche(t_fd *fd, t_env *e, char *cmd);
void			action_inventaire(t_fd *fd, t_env *env, char *cmd);
void			move_ressources(t_env *e, int y, int x);
void			broadcast_pos(t_coord src, t_coord dest, t_coord *new, t_env *e);
void			graph_elevation(t_env *e, int x, int y, int success);
void			action_elevation(t_fd *fd, t_env *e, char *cmd);
void			action_incantation(t_fd *fd, t_env *e, char *cmd);
int			action_broadcast_direction(int dest_x, int dest_y);
void			action_broadcast(t_fd *fd, t_env *e, char *cmd);
void			graph_broadcast(t_env *e, t_fd *fd, char *cmd);
void			broadcast_contenu(char **cmd2, t_fd *fd, t_env *e, char *cmd);
int			action_broadcast_init(t_fd *fd, char *cmd, char **cmd2);
void			graph_newplayer(t_env *e, t_fd *fd);
void			action_connect(t_fd *fd, t_env *e, char *cmd);
void			player_join_team(t_fd *fd, t_team *team, t_env *e);
void			start_fork(t_fd *fd, t_env *e, char *cmd);
void			end_fork(t_fd *fd, t_env *e, char *cmd);
void			graph_fork(t_egg *new, t_fd *fd, t_env *e);
void			action_expulse(t_fd *fd, t_env *e, char *cmd);
int			action_expulse_place(int expulseur, int victime);
void			action_prendre(t_fd *fd, t_env *e, char *cmd);
void			action_poser(t_fd *fd, t_env *e, char *cmd);
int			object_id(char	*tab);
void			graph_prend(t_fd *fd, t_env *e, int idobjet);
void			graph_pose(t_fd *fd, t_env *e, int idobjet);
void	       		join_graph(t_fd *fd, t_env *e);
void	       		sendbct(t_fd *fd, t_env *e);
void			sendtna(t_fd *fd, t_env *e);
void			sendpnw(t_fd *fd, t_env *e);
void			sendenw(t_fd *fd, t_env *e);
void			map_size(t_fd *fd, t_env *e, char *cmd);
void			grh_bct(t_fd *fd, t_env *e, char *cmd);
void			grh_mct(t_fd *fd, t_env *e, char *cmd);
void			grh_tna(t_fd *fd, t_env *e, char *cmd);
void			grh_ppo(t_fd *fd, t_env *e, char *cmd);
void			grh_plv(t_fd *fd, t_env *e, char *cmd);
void			grh_pin(t_fd *fd, t_env *e, char *cmd);
void			grh_sgt(t_fd *fd, t_env *e, char *cmd);
void			grh_sst(t_fd *fd, t_env *e, char *cmd);
void			graph_incantation(t_env *e, t_fd *fd);
void			check_endgame(t_fd *fd, t_env *e, char *cmd);

#endif /* SERVER_H_ */
